<?php 

class Mdb {

    /**
     * 执行Mysql数据库查询语句
     *
     * @param array $db 数据库配置数组
     * @param string|array $sqls 单条sql语句，或sql语句数组
     * @param array $params 查询mysql时与sql语句配合的参数
     * @return array 读取到数据，则返回数据数组。否则返回null
     */
    public static function query(array $db, $sqls, $params = null) {
        $pdo = self::_pdo($db);

        // 如果sqls是字符串，则将sqls和params都转换为数组，否则，验证其数量是否相等
        if (is_string($sqls)){
            $sqls = [$sqls];
            $params = [$params];
        }

        // 执行数据查询，关闭pdo
        $stmts = [];
        $i = 0;
        foreach ($sqls as $key=>$sql){
            $stmt = $pdo->prepare($sql);
            if (!$stmt->execute($params[$i])) {
                throw new Exception('trsql::query，查询时出现错误，出错语句：' . $sql . '，出错参数：' . $params[$i]);
            }
            $stmt->setFetchMode(PDO::FETCH_ASSOC);
            $stmts[] = $stmt;
            $i++;
        }

        // 将结果与MongoDB一样做成数组返回
        $result = null;
        if (count($stmts) === 1) {
            $result = $stmts[0]->fetchAll();
        } else {
            $result = [];
            $i = 0;
            foreach ($sqls as $key=>$val){
                $result[$key] = $stmts[$i]->fetchAll();
                $i++;
            }
        }
        return $result;
    }

    /**
     * write
     *
     * @param array $db 数据库配置数组
     * @param string||array $sqls 单条sql语句，或sql语句数组
     * @param array $params 查询mysql时与sql语句配合的参数
     * @return boolean 成功返回true，失败返回false
     */
    public static function write(array $db, $sqls, $params = null) {
        // 如果是多条操作，则使用事物
        if (is_array($sqls)){
            return self::_transaction($db, $sqls, $params);
        }
        
        // 执行单条数据操作
        $pdo = self::_pdo($db);
        $stmt = $pdo->prepare($sqls);
        $result = $stmt->execute($params);
        $pdo = null;
        if (!$result) {
            throw new Exception('trsql::write，查询时出现错误，出错语句：' . $sqls);
        }
        return $result;
    }

    /**
     * lastid
     *
     * @param array $db 数据库配置数组
     * @param string $sql 单条sql语句
     * @param array $params 与sql配合的params参数的值
     * @return int 成功则返回被插入数据的id号
     */
    public static function lastid(array $db, string $sql, $params = null){
        $pdo = self::_pdo($db);
        $stmt = $pdo->prepare($sql);
        $result = $stmt->execute($params);
        $lastId = $pdo->lastInsertId();
        $pdo = null;
        return $lastId;
    }

    /**
     * _transaction
     */
    private static function _transaction(array $db, array $sqls, array $params){
        $pdo = self::_pdo($db, 0);
        $pdo->beginTransaction();
        foreach ($sqls as $key=>$sql){
            $stmt = $pdo->prepare($sql);
            if (!$stmt->execute($params[$key])) {
                $pdo->rollBack();
                throw new Exception('trsql::_transaction，事物操作时出现错误，出错语句：' . $sql . '，出错参数：' . $params[$key]);
                return false;
            }
        }
        $pdo->commit();
        $pdo = null;
        return true;
    }

    /**
     * _pdo
     */
    private static function _pdo(array $db, int $autocommit = 1){
        $pdo = new PDO($db['host'], $db['user'], $db['pwd']);
        $pdo->query("set names utf8");
        $pdo->setAttribute(PDO::ATTR_AUTOCOMMIT, $autocommit);
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $pdo->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
        $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
        return $pdo;
    }
}
